package l1j.opqlo.NewSystem.Extension.FireRoom;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.opqlo.NewSystem.A_ColorMessage;
import l1j.opqlo.NewSystem.Extension.TreasureMaster;
import l1j.opqlo.Server.L1World.L1World;
import l1j.server.server.IdFactory;
import l1j.server.server.datatables.ItemTable;
import l1j.server.server.datatables.MapsTable;
import l1j.server.server.datatables.NpcTable;
import l1j.server.server.model.Getback;
import l1j.server.server.model.L1Inventory;
import l1j.server.server.model.L1Location;
import l1j.server.server.model.L1NpcDeleteTimer;
import l1j.server.server.model.L1Object;
import l1j.server.server.model.L1Party;
import l1j.server.server.model.L1Teleport;
import l1j.server.server.model.Instance.L1DoorInstance;
import l1j.server.server.model.Instance.L1EffectInstance;
import l1j.server.server.model.Instance.L1FieldObjectInstance;
import l1j.server.server.model.Instance.L1ItemInstance;
import l1j.server.server.model.Instance.L1NpcInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.model.Instance.L1PetInstance;
import l1j.server.server.model.Instance.L1SummonInstance;
import l1j.server.server.model.map.L1Map;
import l1j.server.server.serverpackets.S_CharVisualUpdate;
import l1j.server.server.serverpackets.S_EffectLocation;
import l1j.server.server.serverpackets.S_GreenMessage;
import l1j.server.server.serverpackets.S_MapID;
import l1j.server.server.serverpackets.S_OtherCharPacks;
import l1j.server.server.serverpackets.S_OwnCharPack;
import l1j.server.server.serverpackets.S_PacketBoxGame;
import l1j.server.server.serverpackets.S_RedMessage;
import l1j.server.server.serverpackets.S_RemoveObject;
import l1j.server.server.serverpackets.S_SkillIconGFX;
import l1j.server.server.serverpackets.S_SystemMessage;
import l1j.server.server.serverpackets.S_Weather;
import l1j.server.server.utils.Random;
import l1j.server.server.utils.collections.Lists;
import l1j.server.server.utils.collections.Maps;

public class FireRoom {
	private static final Logger _log = Logger.getLogger(FireRoom.class.getName());
	private short _mapId;
	private List<L1PcInstance>_pcList = Lists.newConcurrentList();//new CopyOnWriteArrayList<E>(同步集合);//目前副本內的玩家物件
	private Map<Integer , Boolean>_trapMap;// 踏板編號
	private int _waitSec;
	private byte _gameStatus = -1;
	private int _boss1Type; //第一關BOSS類型
	private static int[]_boss1Loc={//第一關BOSS座標
		32741, 32883, // 左
		32741, 32906// 右
	};
	private static int[]FIRST_BOSS_ID ={710069 , 710070};
	private static int TRAP_ID =710068;//	結界踏板
	private static int[]TRAP_X = {32713,32695,32695,32682,32688,32713,32682,32688,32713 };
	private static int[]TRAP_Y = {32865,32867,32870,32876,32884,32915,32914,32906,32875 };
	private static int[]FINAL_BOSS_ID = {
		710093	,	//	巴拉卡斯
		710094	,	//	林德拜爾
		710095	,	//	安塔瑞斯
		710096		//	法利昂
	};


	public FireRoom(final short mapid , final L1Party party){
		_mapId = mapid;
		for(final L1PcInstance pc : party.getMembers()){
			pc.inQuestGame = true;
			_pcList.add(pc);
		}
		this.GreenMessage("準備進入副本，10秒後將自動傳送。", true, 10);
		_waitSec = 10;
		_gameStatus = 0;
	}

	public boolean RunGame(){
		try{
			if(_gameStatus !=0 && checkPc() == false){//檢查
				return false;
			}
			if(_gameStatus <0){
				return false;
			}
			switch(_gameStatus){
			case 0://玩家開始入場 等候10秒
				if(_waitSec>0){
					_waitSec--;
				}else{
					GreenMessage("副本將於10秒後開始，請在時間內擊殺怪物獲取【魔族密令】來召喚出副本BOSS。", true, 10);
					TeleportOderY(32728, 32894 , 32895 , 0);
					_waitSec = 10;
					setStatus(1);
				}
				break;
			case 1://第一波小怪開始 創怪
				if(_waitSec >0){
					_waitSec--;
				}else{
					_waitSec = 900;
					setStatus(2);
					GreenMessage("副本開始!!請擊殺怪物獲取【魔族密令】來召喚出副本BOSS。", true , 900);
					this.spawn(
							77072026,//_ItemId,
							710066	,//_npcId[i],火焰強弩手
							300,
							0,
							0,
							(short) _mapId, 0, 0, false);
				}
				break;
			case 2://等待玩家清怪
				checkTime();//確認等候時間(<0 會結束副本)
				break;
			case 3://第一波BOSS出場準備(觸發魔界密令)
				clearNpc();
				_waitSec = 3;
				setStatus(4);
				final int chance = Random.nextInt(100)+1;
				final S_EffectLocation packet;
				if(chance>50){
					RedMessage("死亡的氣息瞬間侵入你的腦中...");
					TeleportOderY(32736 , 32880 , 32888 , 2);
					packet =new S_EffectLocation(32741, 32883, 4848);
					_boss1Type = 1;
				}else{
					RedMessage("混沌突然籠罩著周遭一切...");
					TeleportOderY(32736 , 32903 , 32911 , 2);
					packet =new S_EffectLocation(32741, 32906, 4848);
					_boss1Type =2;
				}
				final L1PcInstance tgpc = _pcList.get(0);
				tgpc.sendPacketsX8(packet);
//				final Iterator<L1PcInstance>ite = this._pcList.iterator();
//				while(ite.hasNext()){
//					final L1PcInstance pc = ite.next();
//					pc.sendPackets(packet);
//				}
				break;
			case 4://召喚副本第一關BOSS
				if(_waitSec >0){
					_waitSec--;
					updateTime();
				}else{
					setStatus(5);//擊殺BOSS倒數計時
					_waitSec = 600;
					if(_boss1Type == 1){
						TreasureMaster.getInstance().spawn(
								0,//_ItemId,
								FIRST_BOSS_ID[0]	,//_npcId[i],死亡
								1,
								_boss1Loc[0],
								_boss1Loc[1],
								(short) _mapId, 0, 0, true);
					}else{
						TreasureMaster.getInstance().spawn(
								0,//_ItemId,
								FIRST_BOSS_ID[1]	,//_npcId[i],混沌
								1,
								_boss1Loc[2],
								_boss1Loc[3],
								(short) _mapId, 0, 0, true);	
					}
				}
				break;
			case 5: //等候玩家擊殺BOSS
				checkTime();//確認等候時間(<0 會結束副本)
				break;
			case 6: //踏板召喚
				clearNpc();
				setStatus(7);//倒數計時
				_waitSec = 600;
				GreenMessage("[溫柔的聲音]:勇士們請尋找可以打開結界的機關，我已經幫你們點亮它們了。" , false , 0);
				final int setNumber =Random.nextInt(TRAP_X.length);
				L1EffectInstance eff = null;
				_trapMap = Maps.newHashMap();
				for(int i=0; i <TRAP_X.length; i++){
					eff =(L1EffectInstance) TreasureMaster.getInstance().spawn(
							0,//_ItemId,
							TRAP_ID	,//_npcId
							1,
							TRAP_X[i],
							TRAP_Y[i],
							(short) _mapId, 0, 0, false)[0];
					if(i == setNumber){
						_trapMap.put(eff.getId(), false);//正確的踏板(不生怪)
					}else{
						_trapMap.put(eff.getId(), true);//錯誤的踏板(會生怪)
					}
				}
				break;
			case 7://等候玩家觸發正確踏板
				checkTime();//確認等候時間(<0 會結束副本)
				break;
			case 8://觸發正確踏板，準備召喚BOSS
				clearNpc();
				GreenMessage("[宙斯]:不好了，這是一個陷阱...。" , false , 0);
				_waitSec = 10;
				setStatus(9);//最終BOSS出現倒數
				break;
			case 9:
				if(_waitSec >0){
					switch(_waitSec){
					case 8:
						TeleportOderY(32678 , 32894 , 32895 , 6);
						break;
					case 6:
						RedMessage("[肯恩]:宙斯!你千方百計想要阻止我，現在你將自食其果。");
						break;
					case 2:
						RedMessage("[肯恩]:別自不量力想阻止席林的復活。");
						break;
					}
					_waitSec--;
				}else{
					GreenMessage("[宙斯]:這是...龍的氣息? 勇士們...要多加小心。" , false , 0);
					_waitSec =2;
					setStatus(10);//最終BOSS出現
				}
				break;
			case 10:
				if(_waitSec >0){
					if(_waitSec ==2){
						finalBoosEffect();
					}
					_waitSec--;
				}else{
					final int random = Random.nextInt(FINAL_BOSS_ID.length);
					spawn(0, FINAL_BOSS_ID[random], 1, 32671, 32894, _mapId, 0, 0, true);
					_waitSec = 600;
					setStatus(11);//擊敗BOSS倒數
				}
				break;
			case 11:
				checkTime();//確認等候時間(<0 會結束副本)
				break;
			case 99://測試結束
				gameOver();
				break;
			}//switch End
		}catch(Exception e){
			_log.log(Level.SEVERE, e.getLocalizedMessage() , e);
			return false;
		}
		return true;
	}

	/**BOSS出現特效*/
	private void finalBoosEffect(){
		final L1PcInstance tgpc = _pcList.get(0);
		tgpc.sendPacketsX8(new S_EffectLocation(32671 , 32894 , 4784));
	}

	/**確認等候時間(<0 會結束副本)*/
	private void checkTime(){
		if(_waitSec >0){
			_waitSec--;
			updateTime();
		}else{//時間結束
			gameOver();
		}
	}

	/**設定副本狀態*/
	public void setStatus(final int b){
		_gameStatus = (byte) b;
	}
	/** 特定NPC死亡後觸發任務 */
	public void npdDead(final int npcid) {
		if(npcid == FIRST_BOSS_ID[0] || npcid == FIRST_BOSS_ID[1]){
			setStatus(6);
		}else{
			for(final int bossid : FINAL_BOSS_ID){
				if(bossid == npcid){
					setStatus(99);
					break;
				}
			}
		}
	}

	public void reJoinRoom(final L1PcInstance pc){
		if(_gameStatus <0 || _pcList.isEmpty()){
			pc.sendPackets(new S_SystemMessage("這個副本已經結束了。"));
		}else if(_pcList.contains(pc)){
			pc.sendPackets(new S_SystemMessage("你已經在副本中或是程式正忙碌中，請稍後再試。"));
		}else{
			final L1PcInstance tgpc = _pcList.get(0);
			L1Teleport.teleportByMagic(pc, tgpc.getX(), tgpc.getY(), _mapId, 5, true);
			_pcList.add(pc);
		}
	}


	/** 發送綠色訊息(是否含時間) **/
	private void GreenMessage(final String msg, final boolean haveTime,final int Time) {
		final Iterator<L1PcInstance>ite = this._pcList.iterator();
		while(ite.hasNext()){
			final L1PcInstance pc = ite.next();
			pc.sendPackets(new S_GreenMessage(msg));
			pc.sendPackets(new A_ColorMessage(15, msg));
			if (haveTime && Time > 0) {
				pc.sendPackets(new S_SkillIconGFX(71, Time));// opqlo
				// 特殊地圖計時顯示
			}
		}
	}
	/** 發送紅色訊息 **/
	private void RedMessage(final String msg) {
		final Iterator<L1PcInstance>ite = this._pcList.iterator();
		while(ite.hasNext()){
			final L1PcInstance pc = ite.next();
			pc.sendPackets(new S_RedMessage(msg));
		}
	}

	/** 傳送玩家 */
	private void TeleportOderY(int x, int y, final int yy, final int head) {
		final int srcy = y;
		L1PcInstance pc;
		for (int i = 0; i < this._pcList.size(); i++) {
			pc = this._pcList.get(i);
			if (!pc.isDead()) {
				L1Teleport.teleportByMagic(pc, x, y, (short) this._mapId, head, true);
				if (y <= yy) {
					x--;
					y = srcy;
				}
				y--;
			}
		}
		// L1Teleport.teleport(pc, loc, head, effectable)
	}

	/**踏板觸發任務*/
	public void TrapAcvion(final L1EffectInstance effect){
		final Boolean spawn = _trapMap.get(effect.getId());
		if(spawn == null){
			return;
		}
		if(spawn){
			TreasureMaster.getInstance().spawn(0,710067, 6, effect.getX(), effect.getY(),(short) this._mapId, 5, 0, false);
		}else if(_gameStatus ==7){
			setStatus(8);
		}
	}
	// 召喚用
	private L1NpcInstance[] spawn(final int Itemid, final int npcId,
			final int count, final int X, final int Y, final short mapId,
			final int randomRange, final int timeMillisToDelete,
			final boolean isBOSS) {
		boolean AreaSpawn = false;
		final L1NpcInstance[] _npc = new L1NpcInstance[count];
		if (X == 0 || Y == 0) {
			AreaSpawn = true;
		}
		int locx1 = 0, locx2 = 0, locy1 = 0, locy2 = 0, RandomNpcGetItem = 0;
		L1ItemInstance item = null;
		if (Itemid > 0) {
			item = ItemTable.getInstance().createItem(Itemid);
		}
		if (AreaSpawn) {
			final int[] mapXY = MapsTable.getInstance().getTemplate(mapId);
			locx1 = mapXY[0];
			locx2 = mapXY[1];
			locy1 = mapXY[2];
			locy2 = mapXY[3];
		}
		if (item != null) {
			RandomNpcGetItem = Random.nextInt(count) + 1;
		}
		L1NpcInstance npc = null;
		for (int i = 0; i < count; i++) {
			try {
				npc = NpcTable.getInstance().newNpcInstance(npcId);
				npc.setId(IdFactory.getInstance().nextId());
				npc.setMap(mapId);
				if (isBOSS) {
					npc.isQuestMob = true;
					final S_EffectLocation packet1 = new S_EffectLocation(32845, 32832, 761);
					npc.broadcastPacketAll(packet1);
				}

				if (randomRange == 0 && count == 1) {
					npc.setX(X);
					npc.setY(Y);
					if (item != null) {
						item.setCount(1);
						npc.getInventory().storeItem(item);
					}
				} else {
					int tryCount = 0;
					do {
						if (item != null) {
							if (i == RandomNpcGetItem) {// 創造通關道具至NPC身上
								item.setCount(1);
								npc.getInventory().storeItem(item);
								item = null;
							}

						}
						if (AreaSpawn) {
							final L1Map map = npc.getMap();
							final int rangeX = locx2 - locx1;
							final int rangeY = locy2 - locy1;
							npc.setX(Random.nextInt(rangeX) + locx1);
							npc.setY(Random.nextInt(rangeY) + locy1);
							final L1Location location = npc.getLocation();
							if (map.isInMap(location)
									&& map.isPassable(location)) {
								break;
							}
						} else {
							tryCount++;
							npc.setX(X + Random.nextInt(randomRange)- Random.nextInt(randomRange));
							npc.setY(Y + Random.nextInt(randomRange)- Random.nextInt(randomRange));
							final L1Location location = npc.getLocation();
							final L1Map map = npc.getMap();
							if (map.isInMap(location)
									&& map.isPassable(location)) {
								break;
							}
						}
						Thread.sleep(1);
					} while (tryCount < 50);

					if (tryCount >= 50) {
						npc.setX(X);
						npc.setY(Y);
					}
				}
				npc.addHitup(500);
				npc.setHomeX(npc.getX());
				npc.setHomeY(npc.getY());
				npc.setHeading(Random.nextInt(8));
				// npc.setPortalNumber(portalNumber);

				L1World.getInstance().storeObject(npc);
				L1World.getInstance().addVisibleObject(npc);
				/*
				 * if (npc.getGfxId() == 7548 || npc.getGfxId() == 7550 ||
				 * npc.getGfxId() == 7552 || npc.getGfxId() == 7554 ||
				 * npc.getGfxId() == 7585 || npc.getGfxId() == 7539 ||
				 * npc.getGfxId() == 7557 || npc.getGfxId() == 7558 ||
				 * npc.getGfxId() == 7864 || npc.getGfxId() == 7869 ||
				 * npc.getGfxId() == 7870) {
				 * npc.npcSleepTime(ActionCodes.ACTION_AxeWalk,
				 * L1NpcInstance.ATTACK_SPEED); for (final L1PcInstance pc :
				 * L1World.getInstance().getVisiblePlayer(npc)) {
				 * npc.onPerceive(pc); final S_DoActionGFX gfx = new
				 * S_DoActionGFX(npc.getId(), ActionCodes.ACTION_AxeWalk);
				 * pc.sendPackets(gfx); } }
				 */

				npc.turnOnOffLight();
				npc.startChat(L1NpcInstance.CHAT_TIMING_APPEARANCE); // チャット開始

				if (timeMillisToDelete > 0) {
					final L1NpcDeleteTimer timer = new L1NpcDeleteTimer(npc,timeMillisToDelete);
					timer.begin();
				}
				_npc[i] = npc;
			} catch (final Exception e) {
			}
		}
		return _npc;
	}
	/**檢查目前副本內的玩家*/
	private boolean checkPc(){
		try{
			if(_pcList.isEmpty()){//地圖中沒有玩家
				gameOver();//結束副本
				return false;
			}
			final Iterator<L1PcInstance> ite = this._pcList.iterator();
			while(ite.hasNext()){
				final L1PcInstance pc = ite.next();
				if(pc.getNetConnection() ==null){
					//				ite.remove();
					_pcList.remove(pc);
				}else if( pc.getMapId() != this._mapId ){
					//				ite.remove();
					_pcList.remove(pc);
					pc.inQuestGame = false;
					pc.sendPackets(new S_PacketBoxGame(S_PacketBoxGame.STARTTIMECLEAR));//移除倒數計時器
				}
			}
			if(_pcList.isEmpty()){//地圖中沒有玩家
				gameOver();//結束副本
				return false;
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return true;
	}

	/**發送目前時間*/
	private void updateTime(){
		final Iterator<L1PcInstance> ite = this._pcList.iterator();
		while(ite.hasNext()){
			final L1PcInstance msgPc = ite.next();
			msgPc.sendPackets(new S_SkillIconGFX(71, _waitSec));// opqlo 特殊地圖計時顯示
		}
	}
	// 重置副本
	private void gameOver() {
		
		setStatus(-1);//副本結束狀態
		final ConcurrentHashMap<Integer, L1Object> map = L1World.getInstance().getVisibleObjects(_mapId);
		if(map.isEmpty() == false){
			final ArrayList<L1Object>list = new ArrayList<L1Object>();
			list.addAll(map.values());
			final Iterator<L1Object> ite = list.iterator();
			while(ite.hasNext()){
				final Object obj = ite.next();
				// 門關閉
				if (obj instanceof L1DoorInstance) {
					final L1DoorInstance door = (L1DoorInstance) obj;
					door.close();
				} else if (obj instanceof L1FieldObjectInstance) {
					final L1FieldObjectInstance field = (L1FieldObjectInstance) obj;
					field.deleteMe();
					/** 清除副本殘留的寵物、召喚獸 **/
				} else if (obj instanceof L1SummonInstance) {
					final L1SummonInstance summon = (L1SummonInstance) obj;
					final L1PcInstance pc = (L1PcInstance) summon.getMaster();
					if (pc != null) {
						pc.getPetList().remove(summon.getId());
					}
					summon.deleteMe();
				} else if (obj instanceof L1PetInstance) {
					final L1PetInstance pet = (L1PetInstance) obj;
					final L1PcInstance pc = (L1PcInstance) pet.getMaster();
					if (pc != null) {
						pc.getPetList().remove(pet.getId());
					}
					pet.stopFoodTimer(pet); // 停止飽食度計時
					pet.setDead(true);// 寵物認知
					pet.dropItem();
					pet.deleteMe();
					// 刪除副本內的怪物
				}else if (obj instanceof L1NpcInstance) {
					final L1NpcInstance npc = (L1NpcInstance) obj;
					if (npc.getMaster() == null) {
						npc.deleteMe();
					}
					// 刪除副本內的物品
				}else if (obj instanceof L1Inventory) {
					final L1Inventory inventory = (L1Inventory) obj;
					inventory.clearItems();
					// 將玩家傳出副本地圖
				}else if (obj instanceof L1PcInstance) {
					final L1PcInstance pc = (L1PcInstance) obj;
					try{
						pc.inQuestGame = false;
						if (pc.isDead()) {
							this.reStartPlayer(pc);
						} else {// 傳送至威頓村
							L1Teleport.teleportByMagic(pc, 33710, 32521, (short) 4 , pc.getHeading(), true);
						}
						if(pc.getNetConnection() !=null){
							pc.sendPackets(new S_PacketBoxGame(S_PacketBoxGame.STARTTIMECLEAR));//移除倒數計時器
						}
					}catch(Exception e){
					}
				}
			}
		}
	}
	
	/**清空上一階段所存怪物*/
	private void clearNpc(){
		final ConcurrentHashMap<Integer, L1Object> map = L1World.getInstance().getVisibleObjects(_mapId);
		if(map.isEmpty() == false){
			final ArrayList<L1Object>list = new ArrayList<L1Object>();
			list.addAll(map.values());
			final Iterator<L1Object> ite = list.iterator();
			while(ite.hasNext()){
				final Object obj = ite.next();
				 if (obj instanceof L1NpcInstance) {
						final L1NpcInstance npc = (L1NpcInstance) obj;
						if (npc.getMaster() == null) {
							npc.deleteMe();
						}
				 }
			}
		}
	}
	
	// 副本內死亡的玩家重新開始
	private void reStartPlayer(final L1PcInstance pc) {
		pc.stopPcDeleteTimer();
		final int[] loc = Getback.GetBack_Location(pc, true);
		pc.removeAllKnownObjects();
		pc.broadcastPacketAll(new S_RemoveObject(pc));
		pc.setCurrentHp(pc.getLevel());
		pc.set_food(40);
		pc.setDead(false);
		pc.setStatus(0);
		L1World.getInstance().moveVisibleObject(pc, loc[2]);
		pc.setX(loc[0]);
		pc.setY(loc[1]);
		pc.setMap((short) loc[2]);
		pc.sendPackets(new S_MapID(pc.getMapId(), pc.getMap().isUnderwater()));
		pc.broadcastPacketAll(new S_OtherCharPacks(pc));
		pc.sendPackets(new S_OwnCharPack(pc));
		pc.sendPackets(new S_CharVisualUpdate(pc));
		pc.startHpRegeneration();
		pc.startMpRegeneration();
		pc.sendPackets(new S_Weather(L1World.getInstance().getWeather()));
		if (pc.getHellTime() > 0) {
			pc.beginHell();
		}
	}

	public int getMapId(){
		return _mapId;
	}
}
